"""
版本状态流转规则配置
定义版本状态之间的流转规则和条件
"""
from dataclasses import dataclass
from typing import Dict, List, Tuple, Optional
from motor.motor_asyncio import AsyncIOMotorDatabase  # pyright: ignore[reportMissingImports]
from bson import ObjectId  # pyright: ignore[reportMissingImports]
import logging

logger = logging.getLogger(__name__)


@dataclass
class TransitionRule:
    """流转规则"""
    from_status: str
    to_status: str
    name: str
    conditions: Dict
    auto_trigger: bool = True
    require_approval: bool = False
    require_reason: bool = False


class VersionTransitionRules:
    """
    版本状态流转规则配置
    
    注意：RULES 中的状态代码（from_status, to_status）需要与状态管理系统中的状态代码保持一致。
    这些状态代码值在类定义时是硬编码的，但实际使用时应该通过状态管理系统动态获取状态代码进行匹配。
    如果状态管理系统中的状态代码发生变化，需要同步更新此处的规则定义。
    """
    
    RULES = [
        # 草稿 -> 规划中
        TransitionRule(
            from_status="draft",
            to_status="planning",
            name="开始规划",
            conditions={
                "require_planned_release_date": True,
                "min_requirement_count": 1,
            },
            auto_trigger=True,
            require_approval=False
        ),
        
        # 规划中 -> 开发中
        TransitionRule(
            from_status="planning",
            to_status="development",
            name="开始开发",
            conditions={
                "min_requirement_count": 1,
                "min_task_count": 1,
                "min_assigned_task_count": 1,
                "min_active_task_count": 1,
            },
            auto_trigger=True,
            require_approval=False
        ),
        
        # 开发中 -> 测试中
        TransitionRule(
            from_status="development",
            to_status="testing",
            name="进入测试",
            conditions={
                "min_task_completion": 0.80,
                "min_requirement_completion": 0.70,
                "min_overall_completion": 0.75,
                "max_unresolved_defect_rate": 0.20,
            },
            auto_trigger=True,
            require_approval=False
        ),
        
        # 测试中 -> 预发布
        TransitionRule(
            from_status="testing",
            to_status="pre_release",
            name="准备发布",
            conditions={
                "min_task_completion": 1.0,
                "min_requirement_completion": 1.0,
                "min_defect_completion": 0.95,
                "min_test_completion": 0.90,
                "min_overall_completion": 0.95,
                "min_test_execution_rate": 0.80,
            },
            auto_trigger=True,
            require_approval=False
        ),
        
        # 预发布 -> 已发布
        TransitionRule(
            from_status="pre_release",
            to_status="released",
            name="正式发布",
            conditions={
                "min_task_completion": 1.0,
                "min_requirement_completion": 1.0,
                "min_defect_completion": 1.0,
                "min_test_completion": 0.95,
                "min_overall_completion": 0.98,
            },
            auto_trigger=False,
            require_approval=True,
            require_reason=True
        ),
        
        # 已发布 -> 已废弃
        TransitionRule(
            from_status="released",
            to_status="deprecated",
            name="废弃版本",
            conditions={
                "require_reason": True,
            },
            auto_trigger=False,
            require_approval=True,
            require_reason=True
        ),
        
        # 已发布 -> 已归档
        TransitionRule(
            from_status="released",
            to_status="archived",
            name="归档版本",
            conditions={
                "min_days_since_release": 90,
            },
            auto_trigger=False,
            require_approval=True,
            require_reason=False
        ),
        
        # 已废弃 -> 已归档
        TransitionRule(
            from_status="deprecated",
            to_status="archived",
            name="归档废弃版本",
            conditions={},
            auto_trigger=False,
            require_approval=True,
            require_reason=False
        ),
        
        # 已归档 -> 已废弃（恢复）
        TransitionRule(
            from_status="archived",
            to_status="deprecated",
            name="从归档恢复",
            conditions={
                "require_reason": True,
            },
            auto_trigger=False,
            require_approval=True,
            require_reason=True
        ),
    ]
    
    @classmethod
    def get_rules_by_from_status(cls, from_status: str) -> List[TransitionRule]:
        """根据源状态获取所有流转规则"""
        return [rule for rule in cls.RULES if rule.from_status == from_status]
    
    @classmethod
    def get_rule(cls, from_status: str, to_status: str) -> Optional[TransitionRule]:
        """获取指定的流转规则"""
        for rule in cls.RULES:
            if rule.from_status == from_status and rule.to_status == to_status:
                return rule
        return None
    
    @classmethod
    def get_auto_trigger_rules(cls, from_status: str) -> List[TransitionRule]:
        """获取自动触发的流转规则"""
        return [
            rule for rule in cls.get_rules_by_from_status(from_status)
            if rule.auto_trigger
        ]
    
    @classmethod
    async def check_rule_conditions(
        cls,
        rule: TransitionRule,
        completion_data: Dict,
        readiness_data: Dict,
        version: Dict,
        db: AsyncIOMotorDatabase
    ) -> Tuple[bool, List[str]]:
        """
        检查流转规则条件是否满足
        
        Returns:
            (是否满足, 未满足的条件列表)
        """
        unmet_conditions = []
        
        for condition_key, condition_value in rule.conditions.items():
            is_met = False
            
            if condition_key == "require_planned_release_date":
                is_met = version.get("planned_release_date") is not None
                if not is_met:
                    unmet_conditions.append("需要设置计划发布日期")
            
            elif condition_key == "min_requirement_count":
                requirement_count = readiness_data.get("requirement_count", 0)
                is_met = requirement_count >= condition_value
                if not is_met:
                    unmet_conditions.append(f"至少需要关联{condition_value}个需求（当前：{requirement_count}）")
            
            elif condition_key == "min_task_count":
                task_count = readiness_data.get("task_count", 0)
                is_met = task_count >= condition_value
                if not is_met:
                    unmet_conditions.append(f"至少需要关联{condition_value}个任务（当前：{task_count}）")
            
            elif condition_key == "min_assigned_task_count":
                assigned_task_count = readiness_data.get("assigned_task_count", 0)
                is_met = assigned_task_count >= condition_value
                if not is_met:
                    unmet_conditions.append(f"至少需要{condition_value}个任务已分配（当前：{assigned_task_count}）")
            
            elif condition_key == "min_active_task_count":
                active_task_count = readiness_data.get("active_task_count", 0)
                is_met = active_task_count >= condition_value
                if not is_met:
                    unmet_conditions.append(f"至少需要{condition_value}个任务处于活跃状态（当前：{active_task_count}）")
            
            elif condition_key == "min_task_completion":
                task_completion = completion_data.get("task_completion", 0.0)
                is_met = task_completion >= condition_value
                if not is_met:
                    unmet_conditions.append(
                        f"任务完成度需达到{condition_value * 100:.0f}%（当前：{task_completion * 100:.1f}%）"
                    )
            
            elif condition_key == "min_requirement_completion":
                requirement_completion = completion_data.get("requirement_completion", 0.0)
                is_met = requirement_completion >= condition_value
                if not is_met:
                    unmet_conditions.append(
                        f"需求完成度需达到{condition_value * 100:.0f}%（当前：{requirement_completion * 100:.1f}%）"
                    )
            
            elif condition_key == "min_defect_completion":
                defect_completion = completion_data.get("defect_completion", 0.0)
                is_met = defect_completion >= condition_value
                if not is_met:
                    unmet_conditions.append(
                        f"缺陷完成度需达到{condition_value * 100:.0f}%（当前：{defect_completion * 100:.1f}%）"
                    )
            
            elif condition_key == "min_test_completion":
                test_completion = completion_data.get("test_completion", 0.0)
                is_met = test_completion >= condition_value
                if not is_met:
                    unmet_conditions.append(
                        f"测试通过率需达到{condition_value * 100:.0f}%（当前：{test_completion * 100:.1f}%）"
                    )
            
            elif condition_key == "min_overall_completion":
                overall_completion = completion_data.get("overall_completion", 0.0)
                is_met = overall_completion >= condition_value
                if not is_met:
                    unmet_conditions.append(
                        f"综合完成度需达到{condition_value * 100:.0f}%（当前：{overall_completion * 100:.1f}%）"
                    )
            
            elif condition_key == "max_unresolved_defect_rate":
                defect_completion = completion_data.get("defect_completion", 1.0)
                unresolved_rate = 1.0 - defect_completion
                is_met = unresolved_rate <= condition_value
                if not is_met:
                    unmet_conditions.append(
                        f"未解决缺陷率需低于{condition_value * 100:.0f}%（当前：{unresolved_rate * 100:.1f}%）"
                    )
            
            elif condition_key == "min_test_execution_rate":
                test_details = completion_data.get("details", {}).get("tests", {})
                total = test_details.get("total", 0)
                total_run = test_details.get("total_run", 0)
                execution_rate = total_run / total if total > 0 else 0.0
                is_met = execution_rate >= condition_value
                if not is_met:
                    unmet_conditions.append(
                        f"测试执行率需达到{condition_value * 100:.0f}%（当前：{execution_rate * 100:.1f}%）"
                    )
            
            elif condition_key == "min_days_since_release":
                actual_release_date = version.get("actual_release_date")
                if actual_release_date:
                    from datetime import datetime, timedelta
                    if isinstance(actual_release_date, str):
                        try:
                            actual_release_date = datetime.fromisoformat(actual_release_date.replace('Z', '+00:00'))
                        except:
                            actual_release_date = None
                    
                    if actual_release_date:
                        days_since = (datetime.utcnow() - actual_release_date.replace(tzinfo=None)).days
                        is_met = days_since >= condition_value
                        if not is_met:
                            unmet_conditions.append(
                                f"发布后需至少{condition_value}天（当前：{days_since}天）"
                            )
                    else:
                        is_met = False
                        unmet_conditions.append("无法获取实际发布时间")
                else:
                    is_met = False
                    unmet_conditions.append("版本尚未发布，无法计算发布时间")
            
            elif condition_key == "require_reason":
                # 这个条件在手动流转时检查，这里直接通过
                is_met = True
            
            if not is_met and condition_key != "require_reason":
                # require_reason 在手动流转时单独检查，不在这里检查
                pass
        
        is_all_met = len(unmet_conditions) == 0
        return is_all_met, unmet_conditions

